package com.crm.service.impl;

import com.auth0.jwt.JWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.crm.constant.dto.BaseFxResponse;
import com.crm.constant.enums.EmployeeProjectStatusEnum;
import com.crm.constant.enums.ProjectStatusEnum;
import com.crm.entity.CrmArticle;
import com.crm.entity.CrmEmployeeProject;
import com.crm.entity.CrmProject;
import com.crm.mapper.CrmEmployeeProjectMapper;
import com.crm.model.bo.EmpProjectApplyBo;
import com.crm.model.bo.EmployeeProjectPageBo;
import com.crm.model.dto.BasePageResult;
import com.crm.model.vo.EmployeeProjectVo;
import com.crm.model.vo.EmployeeVo;
import com.crm.model.vo.ReportCountVo;
import com.crm.service.ICrmEmployeeProjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crm.service.ICrmEmployeeService;
import com.crm.service.ICrmProjectService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import static com.crm.constant.dto.ResultCode.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author CRM_SYSTEM
 * @since 2022-03-30
 */
@Service
public class CrmEmployeeProjectServiceImpl extends ServiceImpl<CrmEmployeeProjectMapper, CrmEmployeeProject> implements ICrmEmployeeProjectService {

    @Autowired
    private ICrmProjectService projectService;

    @Autowired
    private ICrmEmployeeService employeeService;

    @Override
    public BaseFxResponse<Long> saveUpdateEmpPro(EmpProjectApplyBo empProjectApplyBo) {
        EmployeeProjectStatusEnum statusEnum = EmployeeProjectStatusEnum.getByCode(empProjectApplyBo.getStatus());
        if (statusEnum == null) {
            return BaseFxResponse.fail(EXCEPTION_STATUS_FAIL);
        }

//        CrmEmployeeProject employeeProject = this.getOne(new LambdaQueryWrapper<CrmEmployeeProject>()
//                .eq(CrmEmployeeProject::getEmployeeId, empProjectApplyBo.getEmployeeId())
//                .eq(CrmEmployeeProject::getProjectId, empProjectApplyBo.getProjectId()));
        CrmEmployeeProject employeeProject = this.getById(empProjectApplyBo.getId());
        empProjectApplyBo.setEmployeeId(queryEmployeeId());
        if (Objects.nonNull(employeeProject)){
            empProjectApplyBo.setProjectId(employeeProject.getProjectId());
        }
        CrmProject project = projectService.getById(empProjectApplyBo.getProjectId());

        switch (statusEnum) {
            case ORDER_YES:
                if (Objects.nonNull(employeeProject)) {
                    return BaseFxResponse.fail(EXCEPTION_PROJECT_EMP_REPEAT);
                }
                LocalDateTime orderEndTime = project.getOrderEndTime();
                LocalDateTime orderStarterTime = project.getOrderStarterTime();

                LocalDateTime localDateTime = LocalDateTime.now();

                if (localDateTime.isBefore(orderStarterTime)||localDateTime.isAfter(orderEndTime)){
                    return BaseFxResponse.fail(EXCEPTION_PROJECT_EMP_ORDER_DATE);
                }


//                if (!ProjectStatusEnum.PROJECT_ORDER_IN.getCode().equals(project.getProjectStatusCode())) {
//                    return BaseFxResponse.fail(EXCEPTION_PROJECT_EMP_DATE);
//                }
                if (project.getIsFullNumber() == 1) {
                    return BaseFxResponse.fail(EXCEPTION_PROJECT_EMP_FULL);
                }
                employeeProject = new CrmEmployeeProject();
                BeanUtils.copyProperties(empProjectApplyBo, employeeProject);
                employeeProject.setEmployeeId(empProjectApplyBo.getEmployeeId());
                employeeProject.setProjectId(empProjectApplyBo.getProjectId());
                employeeProject.setStatusCode(statusEnum.getCode());
                employeeProject.setStatusName(statusEnum.getValue());
                employeeProject.setOrderTime(LocalDateTime.now());
                this.save(employeeProject);
                Integer employeeNum = queryProjectEmployeeNum(project.getId());
                employeeNum=employeeNum+1;
                project.setCurrentNumber(employeeNum);
                if (employeeNum>=project.getMaxNumber()){
                    project.setIsFullNumber(1);
                    project.setProjectStatusCode(ProjectStatusEnum.PROJECT_ORDER_END.getCode());
                    project.setProjectStatusName(ProjectStatusEnum.PROJECT_ORDER_END.getValue());
                }
                projectService.updateById(project);
                break;
            case ORDER_USE:
                ArrayList<Integer> list = new ArrayList<>(Arrays.asList(ProjectStatusEnum.PROJECT_START.getCode(), ProjectStatusEnum.PROJECT_END.getCode()));
                if (!list.contains(project.getProjectStatusCode())){
                    return BaseFxResponse.fail(EXCEPTION_PROJECT_USE);
                }
                //TODO 应当生成结果集
                employeeProject.setCompletionTime(LocalDateTime.now());
                employeeProject.setStatusCode(statusEnum.getCode());
                employeeProject.setStatusName(statusEnum.getValue());
                this.updateById(employeeProject);
                break;
            case ORDER_INVALID:
                employeeProject.setStatusCode(statusEnum.getCode());
                employeeProject.setStatusName(statusEnum.getValue());
                this.updateById(employeeProject);
                Integer employeeNum2 = queryProjectEmployeeNum(project.getId());
                employeeNum2=employeeNum2-1;
                project.setCurrentNumber(employeeNum2<0?0:employeeNum2);
                if (employeeNum2<project.getMaxNumber()){
                    project.setIsFullNumber(0);
                    if (project.getOrderEndTime().isAfter(LocalDateTime.now())&&
                            project.getProjectStatusCode().equals(ProjectStatusEnum.PROJECT_ORDER_END.getCode())){
                        project.setProjectStatusCode(ProjectStatusEnum.PROJECT_ORDER_IN.getCode());
                        project.setProjectStatusName(ProjectStatusEnum.PROJECT_ORDER_IN.getValue());
                    }
                }
                projectService.updateById(project);
                break;
            case ORDER_CANCEL:
                employeeProject.setStatusCode(statusEnum.getCode());
                employeeProject.setStatusName(statusEnum.getValue());
                this.updateById(employeeProject);
                Integer employeeNum1 = queryProjectEmployeeNum(project.getId());
                employeeNum1=employeeNum1-1;
                project.setCurrentNumber(employeeNum1<0?0:employeeNum1);
                if (employeeNum1<project.getMaxNumber()){
                    project.setIsFullNumber(0);
                    if (project.getOrderEndTime().isAfter(LocalDateTime.now())&&
                            project.getProjectStatusCode().equals(ProjectStatusEnum.PROJECT_ORDER_END.getCode())){
                        project.setProjectStatusCode(ProjectStatusEnum.PROJECT_ORDER_IN.getCode());
                        project.setProjectStatusName(ProjectStatusEnum.PROJECT_ORDER_IN.getValue());
                    }
                }
                projectService.updateById(project);
                break;
            default:
                break;
        }
        return BaseFxResponse.success(employeeProject.getId());
    }

    @Override
    public BaseFxResponse<BasePageResult<EmployeeProjectVo>> queryPage(EmployeeProjectPageBo page) {
        IPage<EmployeeProjectVo> pageParam = new Page<>(page.getPageNumber(), page.getPageSize());
        Long employeeId = queryEmployeeId();
        if (page.getIsCreate()){
            page.setCreateEmployeeId(employeeId);
        }else {
            page.setEmployeeId(employeeId);
        }
        IPage<EmployeeProjectVo> articleIPage =  baseMapper.queryPage(pageParam,page);
        return BaseFxResponse.success(BasePageResult.newInstance(articleIPage));
    }

    @Override
    public List<ReportCountVo> orderCount() {
        return baseMapper.orderCount();
    }

    public Integer queryProjectEmployeeNum(Long projectId){
        return this.count(new LambdaQueryWrapper<CrmEmployeeProject>()
                .eq(CrmEmployeeProject::getProjectId, projectId)
                .in(CrmEmployeeProject::getStatusCode, EmployeeProjectStatusEnum.queryValidStatus()));
    }

    public Long queryEmployeeId(){
        if (RequestContextHolder.getRequestAttributes()==null){
            return null;
        }

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        String token = request.getHeader("token");
        String phone = null;
        if (token != null) {
            phone = JWT.decode(token).getAudience().get(1);
        }
        EmployeeVo employeeVo = employeeService.queryByPhone(phone);
        if (Objects.nonNull(employeeVo)){
            return employeeVo.getId();
        }
        return null;
    }
}
